package heima_bixiangdong.test.review4;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @DESCRIPTION: 这个类是把 ManyProducerAndConsumerDemo 这个多生产多消费的例子用 JDK1.5之后的 锁机制进行了改写，并且提升效率问题
 * @USER: shg
 * @DATE: 2022/11/26 17:52
 */
public class JDK5_Enhance_ManyProducerAndConsumerDemo {
    public static void main(String[] args) {
        // 资源对象
        Resource_3 resource_3 = new Resource_3();

        // 生产任务
        Producer_3 producer_3 = new Producer_3(resource_3);
        // 消费任务
        Consumer_3 consumer_3 = new Consumer_3(resource_3);

        // 第一个生产线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                producer_3.produceBread();
            }
        }, "pro1").start();

        // 第二个生产线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                producer_3.produceBread();
            }
        }, "pro2").start();

        // 第一个消费线程
        new Thread(() -> consumer_3.eatBread(), "con1").start();

        // 第二个消费线程
        new Thread(consumer_3::eatBread, "con2").start();
    }
}

// 资源对象
class Resource_3 {
    private String name;
    private int count = 1;
    private boolean flag = false;
    private Lock lock = new ReentrantLock();
    private Condition pro = lock.newCondition();  // 负责生产
    private Condition con = lock.newCondition();  // 负责消费

    public void setName(String name) {
        // 获取锁
        lock.lock();
        try {
            while (flag) {
                try {
                    pro.await();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            this.name = name + count;
            count++;
            System.out.println(Thread.currentThread().getName() + "...生产者..." + this.name);
            flag = true;
            con.signal();
        } finally {
            lock.unlock();
        }
    }

    public void out(){
        lock.lock();
        try {
            while (!flag){
                try{
                    con.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName()+"...消费者..."+this.name+"--->");
            flag = false;
            pro.signal(); // 此处的condition.signalAll()，并没有提升效率
        }finally {
            lock.unlock();
        }
    }

}

// 生产任务对象
@Data
@AllArgsConstructor
@NoArgsConstructor
class Producer_3 {

    private Resource_3 resource;

    public void produceBread() {
        while (true) {
            resource.setName("面包");
        }
    }
}

// 消费任务对象
@Data
@AllArgsConstructor
@NoArgsConstructor
class Consumer_3 {
    private Resource_3 resource;

    public void eatBread() {
        while (true) {
            resource.out();
        }
    }
}

